const axios = require('axios');
const config = require('../../config/config');
const { setupLogger } = require('../../utils/logger');

class GeckoTerminalService {
  constructor() {
    this.logger = setupLogger();
    this.baseUrl = config.dataSources.geckoTerminal.baseUrl;
    this.rateLimitRemaining = 30;
    this.rateLimitReset = Date.now();
  }

  async fetchData() {
    try {
      this.logger.info('开始获取GeckoTerminal数据...');
      
      // 检查速率限制
      if (this.rateLimitRemaining <= 0 && Date.now() < this.rateLimitReset) {
        this.logger.warn('GeckoTerminal API速率限制，跳过本次获取');
        return [];
      }

      const data = [];
      
      // 获取支持的网络
      const networks = await this.getNetworks();
      data.push(...networks);
      
      // 获取热门池子
      const trendingPools = await this.getTrendingPools();
      data.push(...trendingPools);
      
      // 获取新池子
      const newPools = await this.getNewPools();
      data.push(...newPools);
      
      // 获取特定网络的池子（以太坊和BSC）
      const ethPools = await this.getPoolsByNetwork('eth');
      data.push(...ethPools);
      
      const bscPools = await this.getPoolsByNetwork('bsc');
      data.push(...bscPools);
      
      this.logger.info(`GeckoTerminal数据获取完成，共获取 ${data.length} 条数据`);
      return data;
    } catch (error) {
      this.logger.error('GeckoTerminal数据获取失败:', error);
      return [];
    }
  }

  async getNetworks() {
    try {
      const response = await axios.get(`${this.baseUrl}/networks`);
      
      this.updateRateLimit(response.headers);
      
      return response.data.data
        .slice(0, 20) // 限制数量
        .map(network => ({
          source: 'geckoterminal',
          type: 'network',
          id: network.id,
          name: network.attributes.name,
          coingeckoAssetPlatformId: network.attributes.coingecko_asset_platform_id,
          timestamp: new Date().toISOString()
        }));
    } catch (error) {
      this.logger.error('获取GeckoTerminal网络信息失败:', error);
      return [];
    }
  }

  async getTrendingPools() {
    try {
      const response = await axios.get(`${this.baseUrl}/networks/trending_pools`);
      
      this.updateRateLimit(response.headers);
      
      return response.data.data
        .slice(0, 20) // 限制数量
        .map(pool => ({
          source: 'geckoterminal',
          type: 'trending_pool',
          id: pool.id,
          address: pool.attributes.address,
          name: pool.attributes.name,
          poolCreatedAt: pool.attributes.pool_created_at,
          tokenPriceUsd: parseFloat(pool.attributes.token_price_usd || 0),
          fdvUsd: parseFloat(pool.attributes.fdv_usd || 0),
          marketCapUsd: parseFloat(pool.attributes.market_cap_usd || 0),
          priceChangePercentage: {
            h1: parseFloat(pool.attributes.price_change_percentage?.h1 || 0),
            h6: parseFloat(pool.attributes.price_change_percentage?.h6 || 0),
            h24: parseFloat(pool.attributes.price_change_percentage?.h24 || 0)
          },
          transactions: {
            h1: pool.attributes.transactions?.h1 || {},
            h6: pool.attributes.transactions?.h6 || {},
            h24: pool.attributes.transactions?.h24 || {}
          },
          volumeUsd: {
            h1: parseFloat(pool.attributes.volume_usd?.h1 || 0),
            h6: parseFloat(pool.attributes.volume_usd?.h6 || 0),
            h24: parseFloat(pool.attributes.volume_usd?.h24 || 0)
          },
          timestamp: new Date().toISOString()
        }));
    } catch (error) {
      this.logger.error('获取GeckoTerminal热门池子失败:', error);
      return [];
    }
  }

  async getNewPools() {
    try {
      const response = await axios.get(`${this.baseUrl}/networks/new_pools`);
      
      this.updateRateLimit(response.headers);
      
      return response.data.data
        .slice(0, 20) // 限制数量
        .map(pool => ({
          source: 'geckoterminal',
          type: 'new_pool',
          id: pool.id,
          address: pool.attributes.address,
          name: pool.attributes.name,
          poolCreatedAt: pool.attributes.pool_created_at,
          tokenPriceUsd: parseFloat(pool.attributes.token_price_usd || 0),
          fdvUsd: parseFloat(pool.attributes.fdv_usd || 0),
          marketCapUsd: parseFloat(pool.attributes.market_cap_usd || 0),
          reserveInUsd: parseFloat(pool.attributes.reserve_in_usd || 0),
          timestamp: new Date().toISOString()
        }));
    } catch (error) {
      this.logger.error('获取GeckoTerminal新池子失败:', error);
      return [];
    }
  }

  async getPoolsByNetwork(networkId) {
    try {
      const response = await axios.get(`${this.baseUrl}/networks/${networkId}/pools`, {
        params: {
          page: 1
        }
      });
      
      this.updateRateLimit(response.headers);
      
      return response.data.data
        .slice(0, 10) // 限制数量
        .map(pool => ({
          source: 'geckoterminal',
          type: 'network_pool',
          networkId: networkId,
          id: pool.id,
          address: pool.attributes.address,
          name: pool.attributes.name,
          poolCreatedAt: pool.attributes.pool_created_at,
          tokenPriceUsd: parseFloat(pool.attributes.token_price_usd || 0),
          fdvUsd: parseFloat(pool.attributes.fdv_usd || 0),
          marketCapUsd: parseFloat(pool.attributes.market_cap_usd || 0),
          priceChangePercentage: {
            h1: parseFloat(pool.attributes.price_change_percentage?.h1 || 0),
            h6: parseFloat(pool.attributes.price_change_percentage?.h6 || 0),
            h24: parseFloat(pool.attributes.price_change_percentage?.h24 || 0)
          },
          volumeUsd: {
            h1: parseFloat(pool.attributes.volume_usd?.h1 || 0),
            h6: parseFloat(pool.attributes.volume_usd?.h6 || 0),
            h24: parseFloat(pool.attributes.volume_usd?.h24 || 0)
          },
          timestamp: new Date().toISOString()
        }));
    } catch (error) {
      this.logger.error(`获取GeckoTerminal ${networkId} 网络池子失败:`, error);
      return [];
    }
  }

  async getPoolInfo(networkId, poolAddress) {
    try {
      const response = await axios.get(`${this.baseUrl}/networks/${networkId}/pools/${poolAddress}`);
      
      this.updateRateLimit(response.headers);
      
      const pool = response.data.data;
      return {
        source: 'geckoterminal',
        type: 'pool_info',
        networkId: networkId,
        id: pool.id,
        address: pool.attributes.address,
        name: pool.attributes.name,
        poolCreatedAt: pool.attributes.pool_created_at,
        tokenPriceUsd: parseFloat(pool.attributes.token_price_usd || 0),
        baseTokenPriceUsd: parseFloat(pool.attributes.base_token_price_usd || 0),
        quoteTokenPriceUsd: parseFloat(pool.attributes.quote_token_price_usd || 0),
        baseTokenPriceNativeCurrency: parseFloat(pool.attributes.base_token_price_native_currency || 0),
        quoteTokenPriceNativeCurrency: parseFloat(pool.attributes.quote_token_price_native_currency || 0),
        fdvUsd: parseFloat(pool.attributes.fdv_usd || 0),
        marketCapUsd: parseFloat(pool.attributes.market_cap_usd || 0),
        priceChangePercentage: pool.attributes.price_change_percentage || {},
        transactions: pool.attributes.transactions || {},
        volumeUsd: pool.attributes.volume_usd || {},
        reserveInUsd: parseFloat(pool.attributes.reserve_in_usd || 0),
        timestamp: new Date().toISOString()
      };
    } catch (error) {
      this.logger.error(`获取池子信息失败 ${networkId}/${poolAddress}:`, error);
      return null;
    }
  }

  async getTokenInfo(networkId, tokenAddress) {
    try {
      const response = await axios.get(`${this.baseUrl}/networks/${networkId}/tokens/${tokenAddress}`);
      
      this.updateRateLimit(response.headers);
      
      const token = response.data.data;
      return {
        source: 'geckoterminal',
        type: 'token_info',
        networkId: networkId,
        id: token.id,
        address: token.attributes.address,
        name: token.attributes.name,
        symbol: token.attributes.symbol,
        decimals: token.attributes.decimals,
        totalSupply: token.attributes.total_supply,
        priceUsd: parseFloat(token.attributes.price_usd || 0),
        fdvUsd: parseFloat(token.attributes.fdv_usd || 0),
        marketCapUsd: parseFloat(token.attributes.market_cap_usd || 0),
        totalReserveInUsd: parseFloat(token.attributes.total_reserve_in_usd || 0),
        volumeUsd: token.attributes.volume_usd || {},
        priceChangePercentage: token.attributes.price_change_percentage || {},
        timestamp: new Date().toISOString()
      };
    } catch (error) {
      this.logger.error(`获取代币信息失败 ${networkId}/${tokenAddress}:`, error);
      return null;
    }
  }

  updateRateLimit(headers) {
    // GeckoTerminal API限制为30次/分钟
    this.rateLimitRemaining = Math.max(0, this.rateLimitRemaining - 1);
    if (this.rateLimitRemaining === 0) {
      this.rateLimitReset = Date.now() + 60 * 1000; // 1分钟后重置
    }
  }

  delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  getRateLimitStatus() {
    return {
      remaining: this.rateLimitRemaining,
      resetTime: new Date(this.rateLimitReset).toISOString()
    };
  }
}

module.exports = new GeckoTerminalService();

